package com.windaka.elements.aspect;


import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.windaka.elements.annotation.PageQuery;
import com.windaka.elements.model.dto.BaseDTO;
import com.windaka.elements.utils.ConvertUtils;
import com.windaka.elements.utils.RetPage;
import com.windaka.elements.utils.PageParamUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import static com.github.pagehelper.page.PageMethod.startPage;


/**
 * <p><strong>自动分页</strong></p>
 * <p>
 *     用在Impl实现类的方法上 <br>
 * </p>
 * <li>
 * <p>
 *     <strong>示例1: 默认page1 limit5 @PageQuery</strong> <br>
 *     结果: "result": {返回的Object} <br>
 * </p>
 * </li>
 * <li>
 * <p>
 *     <strong>示例2: 指定page3 limit2 <br> @PageQuery(page = 3, limit = 2)</strong> <br>
 *     结果: 按照方法返回的结果返回(不会自动帮你打包为result) <br>
 * </p>
 * </li>
 * <li>
 * 结果: <br>
 *      "data": { <br>
 *          &nbsp&nbsp "result": {"返回的Object": x}, <br>
 *          &nbsp&nbsp "total": 14, <br>
 *          &nbsp&nbsp "prePage": 0, <br>
 *          &nbsp&nbsp "nextPage": 2, <br>
 *          &nbsp&nbsp "limit": 5, <br>
 *          &nbsp&nbsp "page": 1 <br>
 *      }<br>
 * </li>
 * <li>
 * <p>
 *     <strong>ps: 方法上 有@PageQuery时  @InfoResult不生效</strong> <br>
 * </p>
 * </li>
 * @author song
 * @see PageQuery
 * @since 14:13 2021/8/11
 **/
@Order(1)
@Aspect
@Slf4j
@Component
public class PageAspect {

    @Around("@annotation(pageQuery)")
    public Object pageQuery(ProceedingJoinPoint proceedingJoinPoint, PageQuery pageQuery) throws Throwable {
        // 获取到所以传入的参数
        Object[] objects = proceedingJoinPoint.getArgs();
        BaseDTO baseDTO = new BaseDTO(0, 0);
        for (Object object : objects) {
            if (object instanceof BaseDTO) {
                baseDTO = (BaseDTO) object;
                break;
            }
        }
        // 将注解的值 配置到 DTO 中
        checkConfig(pageQuery, baseDTO);
        // 校验 DTO 值是否正确
        PageParamUtils.checkSqlPage(baseDTO);
        // 进行分页
        Page<?> pageInfo = startPage(baseDTO.getPage(), baseDTO.getLimit());
        // 获取方法的执行结果
        RetPage<?> proceed = (RetPage<?>) proceedingJoinPoint.proceed();
        // 将分页信息 放入返回的数据中
        retPage(pageInfo, proceed);
        return ConvertUtils.null2Empty(proceed, RetPage.class);
    }

    /**
     * 检查 注解的参数 配置 传入的dto
     * @author song
     * @date 16:30 2022/2/17
    **/
    private void checkConfig(PageQuery pageQuery, BaseDTO baseDTO) {
        if (null == baseDTO.getPage()) {
            baseDTO.setPage(pageQuery.page());
        }
        if (null == baseDTO.getLimit()) {
            baseDTO.setLimit(pageQuery.limit());
        }
        if (pageQuery.fixed()) {
            baseDTO.setPage(pageQuery.page());
            baseDTO.setLimit(pageQuery.limit());
        }
    }
    
    /**
     * 将page设置进返回结果
     * @author song
     * @date 15:28 2022/2/18
    **/
    private void retPage(Page<?> page, RetPage<?> retPage) {
        PageInfo<?> pageInfo = new PageInfo<>(page);
        retPage.setPage(pageInfo.getPageNum());
        retPage.setLimit(pageInfo.getPageSize());
        retPage.setTotal(pageInfo.getTotal());
        retPage.setPrePage(pageInfo.getPrePage());
        retPage.setNextPage(pageInfo.getNextPage());
    }

}
